package com.davidfauthoux.client;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * @author David Fauthoux, based on the work from Uwe Maurer http://code.google.com/p/hotforcode/
 *
 */
public final class ChromelessPlayer {
	
	private ChromelessPlayer() {
	}
	
	public static enum State {
		READY,
		STOPPED,
		PLAYING,
		PAUSED,
		LOADING,
		CUED
	}
	
	public interface Listener {
		public void onStateChange(State state);
	}
	
	public static final class Player {
		private final HTML html;
		private final String objectId;
		private Player(HTML html, String objectId) {
			this.html = html;
			this.objectId = objectId;
		}
		
		public Widget getWidget() {
			return html;
		}
		
		public void destroy() {
			unregister(objectId);
			html.setHTML("");
		}

		public native void load(String videoId, int startSeconds) /*-{
			var ytplayer = $doc.getElementById(this.@com.davidfauthoux.client.ChromelessPlayer$Player::objectId);
			ytplayer.loadVideoById(videoId, startSeconds);
			ytplayer.setVolume(100);
		}-*/;
		public native void stop() /*-{
			var ytplayer = $doc.getElementById(this.@com.davidfauthoux.client.ChromelessPlayer$Player::objectId);
			ytplayer.stopVideo();
		}-*/;
	}
	
	private static final Map<String, Listener> listeners = new HashMap<String, Listener>();

	public static Player register(int width, int height, Listener listener) {
		String objectId = "ytplayer" + System.currentTimeMillis();
		listeners.put(objectId, listener);
		HTML html = Utils.createSwf("http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=" + objectId, objectId, width, height);
		return new Player(html, objectId);
	}
	
	private static native void register() /*-{
		$wnd.onYouTubePlayerReady = function(id) {
			var ytplayer = $doc.getElementById(id);
			if (ytplayer == null) {
				return;
			}
			
	       	var event = @com.davidfauthoux.client.ChromelessPlayer$State::READY;
	        @com.davidfauthoux.client.ChromelessPlayer::handleState(Ljava/lang/String;Lcom/davidfauthoux/client/ChromelessPlayer$State;)(id, event);
	        
	        $wnd["ytlistener" + id] = function(state) {
	        	switch (state) {
	        		case 0:
	        			event = @com.davidfauthoux.client.ChromelessPlayer$State::STOPPED;
	        			break;
	        		case 1:
	        			event = @com.davidfauthoux.client.ChromelessPlayer$State::PLAYING;
	        			break;
	        		case 2:
	        			event = @com.davidfauthoux.client.ChromelessPlayer$State::PAUSED;
	        			break;
	        		case 3:
	        			event = @com.davidfauthoux.client.ChromelessPlayer$State::LOADING;
	        			break;
	        		case 5:
	        			event = @com.davidfauthoux.client.ChromelessPlayer$State::CUED;
	        			break;
	        		default:
	        			event = null;
	        			break;
	        	}
	        	if (event != null) {
	        		@com.davidfauthoux.client.ChromelessPlayer::handleState(Ljava/lang/String;Lcom/davidfauthoux/client/ChromelessPlayer$State;)(id, event);
	        	}
	        };
	        
	      	ytplayer.addEventListener("onStateChange", "ytlistener" + id); // youtube API is a bunch of craps, why the hell did not they use the function type?
		};
	}-*/;
	
	static {
		register();
	}
	
	@SuppressWarnings("unused")
	private static void handleState(String id, State state) {
		Listener l = listeners.get(id);
		if (l == null)
			return;
		l.onStateChange(state);
	}
	
	private static void unregister(String id) {
		listeners.remove(id);
		unregisterListener(id);
	}
	
	private static native void unregisterListener(String id) /*-{
		$wnd["ytlistener" + id] = function(state) {}; // no removeEventListener in youtube API, but this assignment enables the listener to be deleted
	}-*/;

}
